package com.zyl.blog.common.domain.data.bean;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.Fastjson2TypeHandler;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.zyl.blog.common.enums.BusinessType;
import com.zyl.blog.common.enums.OpenStatus;
import com.zyl.blog.common.enums.OperationType;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Map;

/**
 * 龙源博客系统日志实体类
 * 记录系统中各类操作、请求、异常等日志信息
 * @version v1.0
 * @ProjectName: Personal_Blog_Server
 * @Package: com.zyl.blog.common.domain.data.bean
 * @ClassName: LyLog
 * @Description:
 * @Author FinalFantasy
 * @Date 2025/8/11-10:47
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName(value = "ly_log")
@Accessors(chain = true)
public class LyLog implements Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    /**
     * 日志ID(雪花算法生成)
     */
    @TableId(value = "log_id", type = IdType.ASSIGN_ID)
    @JsonProperty("logId")
    private Long logId;

    /**
     * 分布式追踪ID
     * 用于微服务架构中追踪完整请求链路
     */
    @TableField("trace_id")
    @JsonProperty("traceId")
    private String traceId;

    /**
     * 业务类型编码
     * 对应BusinessType枚举
     */
    @TableField("business_type")
    @JsonProperty("businessType")
    private Integer businessType;

    /**
     * 操作类型编码
     * 对应OperationType枚举
     */
    @TableField("operation_type")
    @JsonProperty("operationType")
    private Integer operationType;

    /**
     * 操作描述
     * 例如："发布新文章"、"删除评论"等
     */
    @TableField("operation_desc")
    @JsonProperty("operationDesc")
    private String operationDesc;

    /**
     * 操作状态编码
     * 对应OpenStatus枚举
     */
    @TableField("status")
    @JsonProperty("status")
    private Integer status;

    /**
     * 请求参数(JSON格式)
     */
    @TableField(value = "request_params", typeHandler = Fastjson2TypeHandler.class)
    @JsonProperty("requestParams")
    private Map<String, Object> requestParams;

    /**
     * 原始请求参数
     */
    @TableField("raw_params")
    @JsonProperty("rawParams")
    private String rawParams;

    /**
     * 响应结果(JSON格式)
     */
    @TableField(value = "response_result", typeHandler = Fastjson2TypeHandler.class)
    @JsonProperty("responseResult")
    private Object responseResult;

    /**
     * 原始响应结果
     */
    @TableField("raw_result")
    @JsonProperty("rawResult")
    private String rawResult;

    /**
     * 错误代码
     * 操作失败时记录
     */
    @TableField("error_code")
    @JsonProperty("errorCode")
    private String errorCode;

    /**
     * 错误信息
     * 操作失败时记录详细错误原因
     */
    @TableField("error_msg")
    @JsonProperty("errorMsg")
    private String errorMsg;

    /**
     * 调用方法签名
     */
    @TableField("method_signature")
    @JsonProperty("methodSignature")
    private String methodSignature;

    /**
     * 请求URI
     */
    @TableField("request_uri")
    @JsonProperty("requestUri")
    private String requestUri;

    /**
     * 请求方式
     * GET/POST/PUT/DELETE等
     */
    @TableField("request_method")
    @JsonProperty("requestMethod")
    private String requestMethod;

    /**
     * 客户端IP地址
     */
    @TableField("client_ip")
    @JsonProperty("clientIp")
    private String clientIp;

    /**
     * IP地址位置
     */
    @TableField("ip_location")
    @JsonProperty("ipLocation")
    private String ipLocation;

    /**
     * 用户代理信息
     */
    @TableField("user_agent")
    @JsonProperty("userAgent")
    private String userAgent;

    /**
     * 操作时间
     */
    @TableField("operation_time")
    @JsonProperty("operationTime")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime operationTime;

    /**
     * 耗时(毫秒)
     */
    @TableField("cost_time")
    @JsonProperty("costTime")
    private Long costTime;

    /**
     * 操作用户ID
     */
    @TableField("operator_id")
    @JsonProperty("operatorId")
    private Long operatorId;

    /**
     * 操作用户名
     */
    @TableField("operator_name")
    @JsonProperty("operatorName")
    private String operatorName;

    /**
     * 操作部门
     */
    @TableField("operator_dept")
    @JsonProperty("operatorDept")
    private String operatorDept;

    /**
     * 额外信息(JSON格式)
     */
    @TableField(value = "extra_info", typeHandler = Fastjson2TypeHandler.class)
    @JsonProperty("extraInfo")
    private Map<String, Object> extraInfo;

    /* 枚举类型映射，用于Java代码中直接使用枚举 */
    @TableField(exist = false)
    @JsonIgnore
    private BusinessType businessTypeEnum;

    @TableField(exist = false)
    @JsonIgnore
    private OperationType operationTypeEnum;

    @TableField(exist = false)
    @JsonIgnore
    private OpenStatus statusEnum;

    /**
     * 初始化枚举对象
     * 建议在查询后调用此方法
     */
    public void initEnums() {
        if (this.businessType != null) {
            this.businessTypeEnum = BusinessType.fromCode(this.businessType);
        }
        if (this.operationType != null) {
            this.operationTypeEnum = OperationType.fromCode(this.operationType);
        }
        if (this.status != null) {
            this.statusEnum = OpenStatus.fromCode(this.status);
        }
    }

    /**
     * 设置业务类型枚举并同步code值
     */
    public LyLog setBusinessTypeEnum(BusinessType businessTypeEnum) {
        this.businessTypeEnum = businessTypeEnum;
        this.businessType = businessTypeEnum.getCode();
        return this;
    }

    /**
     * 设置操作类型枚举并同步code值
     */
    public LyLog setOperationTypeEnum(OperationType operationTypeEnum) {
        this.operationTypeEnum = operationTypeEnum;
        this.operationType = operationTypeEnum.getCode();
        return this;
    }

    /**
     * 设置状态枚举并同步code值
     */
    public LyLog setStatusEnum(OpenStatus statusEnum) {
        this.statusEnum = statusEnum;
        this.status = statusEnum.getCode();
        return this;
    }
}
